package meetingapplication;

import java.util.Vector;

import tota.middleware.TotaMiddleware;
import tota.tuples.TotaTuple;
import tota.tuples.hop.GradientTuple;
import tuplespace.tuples.SensorTuple;
import tuplespace.tuples.Tuple;
import emulator.agent.AbstractAgent;
import emulator.peers.Peer;
import emulator.peers.PeerInterface_ApplicationSide;
import emulator.utils.GenPoint;

public class MeetAgent extends AbstractAgent {
 
 // this is the grup of peer that will try to meet	
 private static final String[] group = new String[]{"P0","P1","P2"};	
 private static final int speed = 10;
 
 private PeerInterface_ApplicationSide peer;
 private TotaMiddleware tota;
 private boolean ingroup = false;
 
 public MeetAgent(PeerInterface_ApplicationSide peer) {
  this.peer = peer;
  tota = new TotaMiddleware(peer);
  
  for(int i=0; i<group.length;i++)
   if(peer.toString().equals(group[i]))
	ingroup = true;
  
  System.out.println(peer.getAddress() + " starting...");
 }
 
 public void step(int time) {
   tota.step(time);
   // nodes that are not in the meeting group run the TOTA middleware, but don't do anything
   if(!ingroup) return;
   
   // inject the meeting tuple
   if(time == 10) {
    TotaTuple t = new GradientTuple();
    t.setContent("<content=meet>"); // this notation is mandatory
    tota.inject(t);
   }
   
   if(time%50==0) {
    int[] dir = getDirection();
    if(dir != null)
     move(dir[0],dir[1]);
   }
   peer.setColor(255, 0, 255);
 }
 
 private int[] getDirection() {
 //	 read the local tuple space
 GradientTuple mt = new GradientTuple();
 mt.setContent("<content=meet>");
 // read the local tuple space
 Vector local = tota.read(mt);
 
 // look in the local tuple space, the meet tuple with the highest hop counter
 int maxi = 0;
 GradientTuple maxt = (GradientTuple)local.get(0);
 for(int i=1; i<local.size(); i++) {  
  GradientTuple t = (GradientTuple)local.get(i);
  if(maxt.hop < t.hop)
   maxt = t;
 }
 
 
 
 if(maxt.hop <= 2) {
  // I am done, all the peers are within one-hop distance
  return null;
 }
 
 System.out.println(tota.toString()+" wants to follow "+maxt.serialize());
 
 // look in the neighbor tuple spaces for neighbor having a lower value of the 
 // max tuple
 GradientTuple tofollow = null;
 Vector remote = tota.readOneHop(mt);
 for(int i=0; i<remote.size(); i++) {  
  GradientTuple t = (GradientTuple)remote.get(i);
  if(t.id.equals(maxt.id) && t.hop < maxt.hop) {
   if(tofollow==null || (tofollow.hop > t.hop))	 
	tofollow = t;
  }
 }
 
 if(tofollow == null)
  return null; // there are no tuples to follow
 
 
 System.out.println(tota.toString()+" wants to reach "+tofollow.from);
  
 // get the radar tuple
 SensorTuple st = new SensorTuple("<sensor=radar><value=*>");
 st = (SensorTuple)tota.keyrd(st);
 int xy[] = parseRadar(st.value,tofollow.from);
 return xy;
 }
 
 // radar example
 // [W][P8@(-72,46,0)][P45@(-100,-11,0)][P55@(-24,1,0)][P74@(71,5,0)][P79@(-69,-42,0)]
 private int[] parseRadar(String radar, String peer) {
  int index = radar.indexOf(peer);
  if(index == -1) return null;
  int startindex = index+peer.length()+2;
  int endindex = radar.indexOf(",0)]", startindex);
  System.out.println(radar);
  radar = radar.substring(startindex, endindex);
  System.out.println(radar);
  int comma = radar.indexOf(",");
  int[] xy = new int[2];
  xy[0] = Integer.parseInt(radar.substring(startindex,comma).trim());
  xy[1] = Integer.parseInt(radar.substring(comma+1,endindex).trim());
  return xy;
 }
 
 
 private void move(int x, int y){
  Peer p = (Peer) peer.getRealIdentity();
  GenPoint current = p.getLocation();
  System.out.println(tota.toString()+"move to ("+x+","+y+")");
  //GenPoint next = current.getDirection(destination, speed);
  //p.emu.move(p.toString(), next);
 }
 
 // interface method empty implementation
 public synchronized void showAgentFrame() {}
 public synchronized void hideAgentFrame() {peer.shutDown();}
 public synchronized Object getRealIdentity() {return this;}
}